home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / gopher / Unix / gopher1.12 / object / GSgopherobj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-11  |  10.0 KB  |  511 lines

  1. /********************************************************************
  2.  * $Author: lindner $
  3.  * $Revision: 1.1.1.3 $
  4.  * $Date: 1993/01/11 19:54:06 $
  5.  * $Source: /home/mudhoney/GopherSrc/release1.11/object/RCS/GSgopherobj.c,v $
  6.  * $Status: $
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: GSgopherobj.c
  14.  * Implement gopher directory functions.
  15.  *********************************************************************
  16.  * Revision History:
  17.  * $Log: GSgopherobj.c,v $
  18.  * Revision 1.1.1.3  1993/01/11  19:54:06  lindner
  19.  * Fixed syntax in UCX #defines. (DuH!)
  20.  *
  21.  * Revision 1.1.1.2  1993/01/08  19:00:00  lindner
  22.  * Mods for UCX
  23.  *
  24.  * Revision 1.1.1.1  1992/12/31  05:01:31  lindner
  25.  * Chnages for VMS.
  26.  *
  27.  * Revision 1.1  1992/12/17  21:03:54  jqj
  28.  * Initial revision
  29.  *
  30.  * Revision 1.1  1992/12/10  23:27:52  lindner
  31.  * gopher 1.1 release
  32.  *
  33.  *
  34.  *********************************************************************/
  35.  
  36. #include "GSgopherobj.h"
  37.  
  38. #if defined(mips) && defined(ultrix)   /*** Gross hack, yuck! ***/
  39. #define _SIZE_T
  40. #endif
  41.  
  42. #include "String.h"
  43. #include <stdio.h>
  44. #include "compatible.h"
  45. extern int DEBUG;
  46.  
  47. /*
  48.  * These are needed for GSconnect().  Ick.
  49.  */
  50. #ifdef VMS
  51. #include <socket.h>
  52. #include <in.h>
  53. #include <file.h>
  54. #include <inet.h>
  55. #include <netdb.h>
  56.  
  57. #else
  58. #include <sys/types.h>
  59. #include <sys/socket.h>
  60. #include <netinet/in.h>
  61. #include <sys/file.h>
  62. #ifndef hpux
  63. #include <arpa/inet.h>
  64. #endif
  65. #include <netdb.h>
  66. #endif  /* not VMS */
  67.  
  68. #include "Malloc.h"
  69.  
  70. /*
  71.  * Make a new gopherobj, set the fields accordingly...
  72.  */
  73.  
  74. GopherObj *
  75. GSnewSet(objtype, Title, Selstr, Host, Port)
  76.   char objtype;
  77.   char *Title;
  78.   char *Selstr;
  79.   char *Host;
  80.   int Port;
  81. {
  82.      GopherObj *temp;
  83.  
  84.      temp = (GopherObj *) malloc(sizeof(GopherObj));
  85.      temp->Selstr   = STRnewSet(Selstr);
  86.      temp->Title    = STRnewSet(Title);
  87.      temp->Host     = STRnewSet(Host);
  88.      temp->iPort    = Port;
  89.      GSsetNum(temp, -1);
  90.      GSsetWeight(temp, 0);
  91.  
  92.      return(temp);
  93. }
  94.  
  95.  
  96. /*
  97.  * Make a new gopherobj...  Should reuse destroyed GopherObjs...
  98.  */
  99.  
  100. GopherObj *
  101. GSnew()
  102. {
  103.      GopherObj *temp;
  104.  
  105.      temp = (GopherObj *) malloc(sizeof(GopherObj));
  106.      temp->Selstr = STRnew();
  107.      temp->Title  = STRnew();
  108.      temp->Host   = STRnew();
  109.  
  110.      GSinit(temp);
  111.      
  112.      return(temp);
  113. }
  114.  
  115. void
  116. GSdestroy(gs)
  117.   GopherObj *gs;
  118. {
  119.      STRdestroy(gs->Selstr);
  120.      STRdestroy(gs->Title);
  121.      STRdestroy(gs->Host);
  122.  
  123.      free(gs);
  124. }
  125.      
  126.  
  127.  
  128. /*
  129.  * Clear out all the crud 
  130.  */
  131.  
  132. void
  133. GSinit(gs)
  134.   GopherObj *gs;
  135. {
  136.      GSsetType(gs, '\0');
  137.      
  138.      STRinit(gs->Title);
  139.      STRinit(gs->Selstr);
  140.      STRinit(gs->Host);
  141.  
  142.      gs->iPort = 0;
  143.      GSsetNum(gs, -1);
  144.      GSsetWeight(gs, 0);
  145. }
  146.  
  147.  
  148. void
  149. GStoNet(gs, sockfd)
  150.   GopherObj *gs;
  151.   int sockfd;
  152. {
  153.      static char buf[1024];
  154.  
  155.      buf[0] = GSgetType(gs);
  156.  
  157.      sprintf(buf + 1, "%s\t%s\t%s\t%d\r\n",
  158.          GSgetTitle(gs),
  159.          GSgetPath(gs),
  160.          GSgetHost(gs),
  161.          GSgetPort(gs));
  162.      
  163.      writestring(sockfd, buf);
  164.      
  165.      if (DEBUG)
  166.       fprintf(stderr, buf);
  167.  
  168. }
  169.  
  170.  
  171. void
  172. GStoNetHTML(gs, sockfd)
  173.   GopherObj *gs;
  174.   int sockfd;
  175. {
  176.      static char buf[1024];
  177.      static char pathbuf[1024];
  178.  
  179.      buf[0] = '\0';
  180.      pathbuf[0] = '\0';
  181.  
  182.      /** Convert Path so that spaces are %20 **/
  183.      Tohexstr(GSgetPath(gs), pathbuf);
  184.  
  185.      sprintf(buf, "<A HREF=http://%s:%d/%s>%s</A>",
  186.          GSgetHost(gs),
  187.          GSgetPort(gs),
  188.          pathbuf,
  189.          GSgetTitle(gs));
  190.  
  191.      writestring(sockfd, buf);
  192.  
  193.      if (DEBUG)
  194.       fprintf(stderr, "HTML: %s", buf);
  195.      
  196.      if (GSgetWeight(gs) != 0) {
  197.       sprintf(buf, "Score: %d\r\n", GSgetWeight(gs));
  198.       writestring(sockfd, buf);
  199.      }
  200.      else
  201.       writestring(sockfd, "\r\n");
  202.  
  203. }
  204.  
  205.  
  206. /*
  207.  * Fill in a GopherObj, given an HREF= link from a WWW anchor..
  208.  * So far only works with http
  209.  */
  210.  
  211. void
  212. GSfromHREF(gs, href)
  213.   GopherObj *gs;
  214.   char *href;
  215. {
  216.      char *cp;
  217.      char *host;
  218.      char path[1024];
  219.      
  220.      if (strncasecmp(href, "http://", 7)==0) {
  221.       host = href +7;
  222.       cp  = strchr(href+7, '/');
  223.       if (cp == NULL)
  224.            return;
  225.       
  226.       *cp = '\0';
  227.       strcpy(path, "GET ");
  228.       strcat(path, cp+1);
  229.       GSsetPath(gs, path);
  230.  
  231.       GSsetType(gs, 'h');
  232.  
  233.       GSsetPath(gs, path);
  234.       
  235.       cp = strchr(host, ':');
  236.       if (cp==NULL) 
  237.            GSsetPort(gs, 80);  /** default WWW port **/
  238.       else {
  239.            GSsetPort(gs, atoi(cp+1));
  240.            *cp = '\0';
  241.       }
  242.  
  243.       GSsetHost(gs, host);
  244.      }
  245. }
  246.       
  247.  
  248.  
  249.  
  250. extern int readfield();
  251. extern int readline();
  252.  
  253. int
  254. GSfromNet(gs, sockfd)
  255.   GopherObj *gs;
  256.   int sockfd;
  257. {
  258.      char foo[1024];
  259.      
  260.      if (readfield(sockfd, foo, 1024)<= 0) {
  261.       /* EOF or error */
  262.       return(-1);
  263.      }
  264.  
  265.      GSsetType(gs, foo[0]);
  266.  
  267.      /** Get the kind of file from the first character **/
  268.      /** Filter out files that we can't deal with **/
  269.  
  270.      switch (GSgetType(gs)) {
  271.        case A_FILE:
  272.        case A_DIRECTORY:
  273.        case A_MACHEX:
  274.        case A_PCBIN:
  275.        case A_CSO:
  276.        case A_INDEX:
  277.        case A_TELNET:
  278.        case A_SOUND:
  279.        case A_UNIXBIN:
  280.        case A_GIF:
  281.        case A_HTML:
  282.        case A_TN3270:
  283.        case A_MIME:
  284.        case A_IMAGE:
  285.       break;
  286.        case A_EOI:
  287.       if (foo[1] == '\r' && foo[2] == '\n')
  288.            return(1);
  289.      default:
  290.     return(-2);  
  291.      }
  292.  
  293.      /** Suck off the User Displayable name **/
  294.      GSsetTitle(gs, foo+1);
  295.      
  296.      /** Suck off the Pathname **/
  297.      if (readfield(sockfd, foo, 1024) == 0)
  298.       return(-1);
  299.      GSsetPath(gs, foo);
  300.  
  301.      /** Suck off the hostname **/
  302.      if (readfield(sockfd, foo, 1024) == 0)
  303.       return(-1);
  304.      GSsetHost(gs, foo);
  305.  
  306.      if (readline(sockfd, foo, 1024)==0)
  307.       return(-1); 
  308.  
  309.      GSsetPort(gs, 0);
  310.  
  311.      /** Get the port number **/
  312.      GSsetPort(gs, atoi(foo));
  313.  
  314.      return(0);
  315. }
  316.  
  317. /** Copy a GopherObj ***/
  318.  
  319. void
  320. GScpy(dest, orig)
  321.   GopherObj *dest, *orig;
  322. {
  323.      dest->sFileType = orig->sFileType;
  324.      dest->iPort     = orig->iPort;
  325.      dest->Itemnum   = orig->Itemnum;
  326.  
  327.      GSsetTitle(dest, GSgetTitle(orig));
  328.      GSsetPath(dest, GSgetPath(orig));
  329.      GSsetHost(dest, GSgetHost(orig));
  330. }
  331.  
  332. /** Compare two GopherObjs ***/
  333.  
  334. int
  335. GScmp(gs1, gs2)
  336.   GopherObj *gs1, *gs2;
  337. {
  338.      if (GSgetTitle(gs1) == NULL)
  339.       return(1);
  340.      if (GSgetTitle(gs2) == NULL)
  341.       return(-1);
  342.  
  343.      return(strcmp(GSgetTitle(gs1), GSgetTitle(gs2)));
  344. }
  345.  
  346.  
  347.  
  348.  
  349. /* GSconnect performs a connection to socket 'service' on host
  350.  * 'host'.  Host can be a hostname or ip-address.  If 'host' is null, the
  351.  * local host is assumed.   The parameter full_hostname will, on return,
  352.  * contain the expanded hostname (if possible).  Note that full_hostname is a
  353.  * pointer to a char *, and is allocated by connect_to_gopher()
  354.  *
  355.  * Errors:
  356.  *
  357.  * -1 get service failed
  358.  *
  359.  * -2 get host failed
  360.  *
  361.  * -3 socket call failed
  362.  *
  363.  * -4 connect call failed
  364.  */
  365.  
  366. int
  367. GSconnect(gs)
  368.   GopherObj *gs;
  369. {
  370.      struct sockaddr_in Server;
  371.      struct hostent *HostPtr;
  372.      int iSock = 0;
  373.      int ERRinet = -1;
  374.  
  375. #ifdef _CRAY
  376.      ERRinet = 0xFFFFFFFF;  /* -1 doesn't sign extend on 64 bit machines */
  377. #endif
  378.  
  379.      /*** Find the hostname address ***/
  380.      
  381.      if ((Server.sin_addr.s_addr = inet_addr(GSgetHost(gs))) == ERRinet) {
  382.       if (HostPtr = gethostbyname(GSgetHost(gs))) {
  383.            bzero((char *) &Server, sizeof(Server));
  384.            bcopy(HostPtr->h_addr, (char *) &Server.sin_addr, HostPtr->h_length);
  385.            Server.sin_family = HostPtr->h_addrtype;
  386.       } else
  387.            return (-2);
  388.      } else
  389.       Server.sin_family = AF_INET;
  390.  
  391.      Server.sin_port = (unsigned short) htons(GSgetPort(gs));
  392.  
  393.      /*** Open the socket ***/
  394.  
  395.      if ((iSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  396.       return (-3);
  397.  
  398. #ifndef UCX
  399.      setsockopt(iSock, SOL_SOCKET, ~SO_LINGER, 0, 0);
  400. #endif
  401.  
  402.      setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, 0, 0);
  403.      setsockopt(iSock, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
  404.  
  405.      /*** Connect ***/
  406.  
  407.      if (connect(iSock, (struct sockaddr *) &Server, sizeof(Server)) < 0) {
  408.       closenet(iSock);
  409.       return (-4);
  410.      }
  411.      return(iSock);
  412. }
  413.  
  414. /*
  415.  * GSfromLink takes an open file descriptor and starts reading from it.
  416.  * It keeps going until it findsL
  417.  *    enough fields for a gopherobj
  418.  *    no data left
  419.  * 
  420.  * returns 0 with success, -1 on an error.
  421.  */
  422.  
  423. #define    G_PATH    (1<<0)
  424. #define    G_TYPE  (1<<1)
  425. #define    G_NAME    (1<<2)
  426. #define    G_PORT    (1<<3)
  427. #define    G_HOST    (1<<4)
  428. #define    G_ALL (G_PATH | G_TYPE | G_NAME | G_PORT | G_HOST)
  429.  
  430. int
  431. GSfromLink(gs, fd, host, port)
  432.   GopherObj *gs;
  433.   int       fd;
  434.   char      *host;
  435.   int       port;
  436. {
  437.      int doneflags = 0;
  438.      char buf[1024];
  439.  
  440.      while ((doneflags != G_ALL) && readline(fd, buf, 1024)) {
  441.       if (buf[0] == '#')
  442.            continue;   /* comment */
  443.  
  444.       ZapCRLF(buf);
  445.  
  446.       if (strncmp(buf, "Type=", 5)==0) {
  447.            GSsetType(gs, buf[5]);
  448.            doneflags |= G_TYPE;
  449.       }
  450.       
  451.       if (strncmp(buf, "Name=", 5)==0) {
  452.            GSsetTitle(gs, buf+5);
  453.            doneflags |= G_NAME;
  454.       }
  455.        
  456.       if (strncmp(buf, "Path=", 5)==0) {
  457.            GSsetPath(gs, buf+5);
  458.            doneflags |= G_PATH;
  459.       }
  460.        
  461.       if (strncmp(buf, "Host=", 5)==0) {
  462.            if (buf[5] == '+' && buf[6] == '\0')
  463.             GSsetHost(gs, host);
  464.            else
  465.             GSsetHost(gs, buf+5);
  466.  
  467.            doneflags |= G_HOST;
  468.       }
  469.       if (strncmp(buf, "Port=", 5)==0) {
  470.            if (buf[5] == '+' && buf[6] == '\0')
  471.             GSsetPort(gs, port);
  472.            else
  473.             GSsetPort(gs, atoi(buf+5));
  474.  
  475.            doneflags |= G_PORT;
  476.       }
  477.       if (strncmp(buf, "Numb=", 5)==0)
  478.            GSsetNum(gs, atoi(buf+5));
  479.       
  480.      }
  481.      return ((doneflags == G_ALL) ? 0 : -1); /* 0 == success */
  482. }
  483.  
  484.  
  485. void
  486. GStoLink(gs, fd)
  487.   GopherObj *gs;
  488.   int fd;
  489. {
  490.      char gtype[2];
  491.      char portnum[16];
  492.      
  493.      gtype[0] = GSgetType(gs);
  494.      gtype[1] = '\0';
  495.  
  496.      writestring(fd, "#");
  497.      writestring(fd, "\nType=");
  498.      writestring(fd, gtype);
  499.      writestring(fd, "\nName=");
  500.      writestring(fd, GSgetTitle(gs));
  501.      writestring(fd, "\nPath=");
  502.      writestring(fd, GSgetPath(gs));
  503.      writestring(fd, "\nHost=");
  504.      writestring(fd, GSgetHost(gs));
  505.      writestring(fd, "\nPort=");
  506.      sprintf(portnum, "%d", GSgetPort(gs));
  507.      writestring(fd, portnum);
  508.      writestring(fd, "\n");
  509. }
  510.  
  511.